<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <style>
    @charset"UTF-8";

    /* CSS Document */
    html,
    body {
      margin: 0;
      padding: 0;
      font-family: 'Open Sans', sans-serif;
      color: #494949;
    }

    #wrapper {
      width: 300px;
      margin: 0 auto;
    }

    .callInfo {
      width: 190px;
      height: 70px;
      float: left;
    }

    #connectedCall .callInfo {
      width: 240px;
    }

    #dialPad div {
      -moz-user-select: -moz-none;
      -khtml-user-select: none;
      -webkit-user-select: none;

      /*
    Introduced in IE 10.
    See http://ie.microsoft.com/testdrive/HTML5/msUserSelect/
    */
      -ms-user-select: none;
      user-select: none;
    }

    .callInfo h3 {
      color: #389400;
      margin: 10px 0 10px 0;
    }

    .callInfo p {
      margin: 0px 25px 0px 0px;
      float: left;
    }

    #answer,
    #hangUp,
    #reject,
    #connectCall,
    #mute {
      color: #FFF;
      background-color: #389400;
      width: 50px;
      height: 50px;
      float: right;
      text-align: center;
      font-size: 30px;
      margin: 10px 0px 10px 0px;
      border-radius: 25px 25px 25px 25px;
      -moz-border-radius: 25px 25px 25px 25px;
      -webkit-border-radius: 25px 25px 25px 25px;
      cursor: pointer;
      cursor: hand;
    }

    #mute:active,
    #connectCall:active,
    #reject:active,
    #hangUp:active,
    #answer:active {
      background-color: #B6B6B6;
      -webkit-box-shadow: 0px 1px 7px 2px rgba(0, 0, 0, 0.45);
      -moz-box-shadow: 0px 1px 7px 2px rgba(0, 0, 0, 0.45);
      box-shadow: 0px 1px 7px 2px rgba(0, 0, 0, 0.45);
      border: none;
    }

    #hangUp,
    #reject {
      -ms-transform: rotate(135deg);
      /* IE 9 */
      -webkit-transform: rotate(135deg);
      /* Chrome, Safari, Opera */
      transform: rotate(135deg);
    }

    #hangUp {
      background-color: #A90002;
    }

    #reject {
      background-color: #FFF;
      color: #A90002;
      margin-right: 10px;
    }

    #connectCall,
    #mute {
      color: #FFF;
      background-color: #389400;
      width: 260px;
      height: 50px;
      font-size: 30px;
      text-align: center;
      margin: 20px 20px 0px 20px;
      border-radius: 5px 5px 5px 5px;
      -moz-border-radius: 5px 5px 5px 5px;
      -webkit-border-radius: 5px 5px 5px 5px;
      cursor: pointer;
      cursor: hand;
    }

    #mute {
      color: #545454;
      margin: 0 auto;
      width: 50px;
      height: 50px;
      margin: 15px 125px 10px 20px;
      border-radius: 25px 25px 25px 25px;
      -moz-border-radius: 25px 25px 25px 25px;
      -webkit-border-radius: 25px 25px 25px 25px;
      background-color: #FFF;
    }

    .muteActive {
      color: #FFF;
      background-color: #389400;
    }

    #to {
      border-bottom: 2px solid #BBBBBB;
    }

    #toField {
      margin-top: 20px;
      padding-left: 10px;
      font-size: 1em;
      font-family: 'Open Sans', sans-serif;
      width: 300px;
      height: 40px;
      border-radius: 2px 2px 2px 2px;
      -moz-border-radius: 2px 2px 2px 2px;
      -webkit-border-radius: 2px 2px 2px 2px;
      border: 0px solid #B8B8B8;
    }

    #dialPad {
      width: 240px;
      height: 308px;
      margin: 0 auto;
    }

    #dialPad div {
      float: left;
      width: 50px;
      height: 50px;
      text-align: center;
      font-size: 26px;
      margin: 25px 15px 0px 15px;
      box-sizing: border-box;
      -moz-box-sizing: border-box;
      -webkit-box-sizing: border-box;
      border-radius: 25px 25px 25px 25px;
      -moz-border-radius: 25px 25px 25px 25px;
      -webkit-border-radius: 25px 25px 25px 25px;
      border: 1px solid #E8E8E8;
      padding-top: 5px;
    }

    #dialPad div:hover {
      background-color: #389400;
      color: #FFF;
      cursor: pointer;
      cursor: hand;
    }

    #dialPad div:active {
      background-color: #B2B2B2;
      -webkit-box-shadow: 0px 1px 7px 2px rgba(0, 0, 0, 0.45);
      -moz-box-shadow: 0px 1px 7px 2px rgba(0, 0, 0, 0.45);
      box-shadow: 0px 1px 7px 2px rgba(0, 0, 0, 0.45);
      border: none;
    }

    .fa {
      margin-top: 11px;
    }

    #answer .fa {
      -webkit-animation: callp 1s;
      animation: callp 1s;
      -webkit-animation-iteration-count: infinite;
      -webkit-animation-direction: alternate;
      -webkit-animation-play-state: running;
      animation-iteration-count: infinite;
      animation-direction: alternate;
      animation-play-state: running;
    }

    @-webkit-keyframes callp {
      from {
        color: #FFF;
      }

      to {
        color: #389400;
      }
    }

    @keyframes callp {
      from {
        color: #FFF;
      }

      to {
        color: #389400;
      }
    }

    #answer {
      -webkit-animation: call 1s;
      animation: call 1s;
      -webkit-animation-iteration-count: infinite;
      -webkit-animation-direction: alternate;
      -webkit-animation-play-state: running;
      animation-iteration-count: infinite;
      animation-direction: alternate;
      animation-play-state: running;
    }

    @-webkit-keyframes call {
      from {
        background: #389400;
      }

      to {
        background: #FFF;
      }
    }

    @keyframes call {
      from {
        background: #389400;
      }

      to {
        background: #FFF;
      }
    }
  </style>
</head>

<body>
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
  <script src="https://jssip.net/download/releases/jssip-3.4.2.js"></script>
  <div id="errorMessage">must set sip uri/password</div>
  <div id="wrapper">
    <div id="incomingCall" style="display: none">
      <div class="callInfo">
        <h3>Incoming Call</h3>
        <p id="incomingCallNumber">Unknown</p>
      </div>
      <div id="answer"> <i class="fa fa-phone"></i></div>
      <div id="reject"> <i class="fa fa-phone"></i></div>
    </div>
    <div id="callStatus" style="display: none">
      <div class="callInfo">
        <h3 id="callInfoText">info text goes here</h3>
        <p id="callInfoNumber">info number goes here</p>
      </div>
      <div id="hangUp"> <i class="fa fa-phone"></i>
      </div>
    </div>
    <!---------TO FIELD---------------------------------------------------->
    <!---------DIALPAD---------------------------------------------------->
    <div id="inCallButtons" style="display: none">
      <div id="dialPad">

        <div class="dialpad-char" data-value="1" unselectable="on">1</div>
        <div class="dialpad-char" data-value="2" unselectable="on">2</div>
        <div class="dialpad-char" data-value="3" unselectable="on">3</div>
        <div class="dialpad-char" data-value="4" unselectable="on">4</div>
        <div class="dialpad-char" data-value="5" unselectable="on">5</div>
        <div class="dialpad-char" data-value="6" unselectable="on">6</div>
        <div class="dialpad-char" data-value="7" unselectable="on">7</div>
        <div class="dialpad-char" data-value="8" unselectable="on">8</div>
        <div class="dialpad-char" data-value="9" unselectable="on">9</div>
        <div class="dialpad-char" data-value="*" unselectable="on">*</div>
        <div class="dialpad-char" data-value="0" unselectable="on">0</div>
        <div class="dialpad-char" data-value="#" unselectable="on">#</div>
      </div>
      <div id="mute">
        <i id="muteIcon" class="fa fa-microphone"></i>
      </div>
    </div>

    <!---------DIAL CONTROLS-------------------------------------------->
    <div id="callControl">
      <div id="to">
        <input id="toField" type="text" placeholder="Enter number here" />
      </div>
      <div id="connectCall"> <i class="fa fa-phone"></i>

      </div>
    </div>
  </div>
</body>
<script>
  /* 
   * How To Use:
   * 1. fill in valid credentials in the config below
   * 2. run the JsFiddle and enjoy
   */


  var socket = new JsSIP.WebSocketInterface('wss://???.???.???.???:8089/ws'); // FILL WSS SERVER

  var configuration = {
    sockets: [socket],
    'uri': '', // FILL SIP URI HERE like sip:sip-user@your-domain.bwapp.bwsip.io
    'password': '', // FILL PASSWORD HERE,
    'username': '', // FILL USERNAME HERE
    'register': true   
  };

  var incomingCallAudio = new window.Audio('http://study.closeeyes.cn/sip.mp3');
  incomingCallAudio.loop = true;
  incomingCallAudio.crossOrigin = "anonymous";
  var remoteAudio = new window.Audio();
  remoteAudio.autoplay = true;
  remoteAudio.crossOrigin = "anonymous";

  var callOptions = {
    mediaConstraints: {
      audio: true,
      video: false
    }
  };

  var phone;
  if (configuration.uri && configuration.password) {
    JsSIP.debug.enable('JsSIP:*'); // more detailed debug output
    phone = new JsSIP.UA(configuration);
    phone.on('registrationFailed', function (ev) {
      alert('Registering on SIP server failed with error: ' + ev.cause);
      configuration.uri = null;
      configuration.password = null;
      updateUI();
    });
    phone.on('newRTCSession', function (ev) {
      var newSession = ev.session;
      if (session) { // hangup any existing call
        session.terminate();
      }
      session = newSession;
      var completeSession = function () {
        session = null;
        updateUI();
      };
      session.on('ended', completeSession);
      session.on('failed', completeSession);
      session.on('accepted', updateUI);
      session.on('confirmed', function () {
        var localStream = session.connection.getLocalStreams()[0];
        var dtmfSender = session.connection.createDTMFSender(localStream.getAudioTracks()[0])
        session.sendDTMF = function (tone) {
          dtmfSender.insertDTMF(tone);
        };
        updateUI();
      });
      session.on('peerconnection', (e) => {
        console.log('peerconnection', e);
        let logError = '';
        const peerconnection = e.peerconnection;

        peerconnection.onaddstream = function (e) {
          console.log('addstream', e);
          // set remote audio stream (to listen to remote audio)
          // remoteAudio is <audio> element on pag
          remoteAudio.srcObject = e.stream;
          remoteAudio.play();
        };

        var remoteStream = new MediaStream();
        console.log(peerconnection.getReceivers());
        peerconnection.getReceivers().forEach(function (receiver) {
          console.log(receiver);
          remoteStream.addTrack(receiver.track);
        });
      });

      if (session.direction === 'incoming') {
        incomingCallAudio.play();
      } else {
        console.log('con', session.connection)
        session.connection.addEventListener('addstream', function (e) {
          incomingCallAudio.pause();
          remoteAudio.srcObject = e.stream;
        });
      }
      updateUI();
    });
    phone.start();
  }

  var session;
  updateUI();

  $('#connectCall').click(function () {
    var dest = $('#toField').val();
    phone.call(dest, callOptions);
    updateUI();
  });


  $('#answer').click(function () {
    session.answer(callOptions);
  });

  var hangup = function () {
    session.terminate();
  };

  $('#hangUp').click(hangup);
  $('#reject').click(hangup);

  $('#mute').click(function () {
    console.log('MUTE CLICKED');
    if (session.isMuted().audio) {
      session.unmute({
        audio: true
      });
    } else {
      session.mute({
        audio: true
      });
    }
    updateUI();
  });
  $('#toField').keypress(function (e) {
    if (e.which === 13) { //enter
      $('#connectCall').click();
    }
  });
  $('#inCallButtons').on('click', '.dialpad-char', function (e) {
    var $target = $(e.target);
    var value = $target.data('value');
    session.sendDTMF(value.toString());
  });

  function updateUI() {
    if (configuration.uri && configuration.password) {
      $('#errorMessage').hide();
      $('#wrapper').show();
      if (session) {
        if (session.isInProgress()) {
          if (session.direction === 'incoming') {
            $('#incomingCallNumber').html(session.remote_identity.uri);
            $('#incomingCall').show();
            $('#callControl').hide()
            $('#incomingCall').show();
          } else {
            $('#callInfoText').html('Ringing...');
            $('#callInfoNumber').html(session.remote_identity.uri.user);
            $('#callStatus').show();
          }

        } else if (session.isEstablished()) {
          $('#callStatus').show();
          $('#incomingCall').hide();
          $('#callInfoText').html('In Call');
          $('#callInfoNumber').html(session.remote_identity.uri.user);
          $('#inCallButtons').show();
          incomingCallAudio.pause();
        }
        $('#callControl').hide();
      } else {
        $('#incomingCall').hide();
        $('#callControl').show();
        $('#callStatus').hide();
        $('#inCallButtons').hide();
        incomingCallAudio.pause();
      }
      //microphone mute icon
      if (session && session.isMuted().audio) {
        $('#muteIcon').addClass('fa-microphone-slash');
        $('#muteIcon').removeClass('fa-microphone');
      } else {
        $('#muteIcon').removeClass('fa-microphone-slash');
        $('#muteIcon').addClass('fa-microphone');
      }
    } else {
      $('#wrapper').hide();
      $('#errorMessage').show();
    }
  }
</script>

</html>